package com.yaorange.web;

import com.github.pagehelper.PageInfo;
import com.yaorange.entity.Dept;
import com.yaorange.entity.Emp;
import com.yaorange.entity.Role;
import com.yaorange.service.DeptService;
import com.yaorange.service.EmpService;
import com.yaorange.service.RoleService;
import com.yaorange.service.async.AsyncService;
import com.yaorange.utils.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@CrossOrigin
@RequestMapping("/personnel/emp")
public class EmpController {
    @Resource
    private EmpService empService;

    @Resource
    private DeptService deptService;

    @Resource
    private RoleService roleService;

    @Autowired
    private AsyncService asyncService;


    //分页功能
    @GetMapping({"/page/{pageNum}/{pageSize}","/page/{pageNum}/{pageSize}/{conditionEmpName}"})
    @ResponseBody
    public PageInfo<Emp> getPage(@PathVariable Integer pageNum,@PathVariable Integer pageSize,
                                 @PathVariable(required = false) String conditionEmpName){
        return empService.getPage(pageNum,pageSize,conditionEmpName);
    }







    //增加员工信息
    //先查询部门有哪些，回显到新增页面上
    @GetMapping("/deptList")
    @ResponseBody
    public List<Dept> getDeptList(){
        return deptService.getDeptList();
    }

    //增加操作
    @PostMapping("/addEmp")
    @ResponseBody
    public Map<String,Object> addEmp(@RequestBody Emp emp){
        //设置追踪数据
        //todo:设置操作员工账户（有权限后设置）
        //设置创建时间
        emp.setCreateTime(new Date());
        //设置新员工的初始密码
        String password = "123456";
        emp.setEmpPassword(password);
        //调用业务层方法增加员工
        int rows=empService.addEmp(emp);
        //准备消息返回给前端
        Map<String,Object> map = new HashMap<>();
        if(rows > 0){
            //将邮件发送封装到异步执行业务方法
            asyncService.asyncSendMail(emp);

            map.put("status",20000);
            map.put("msg","新增员工成功");

        }else{
            map.put("status",30000);
            map.put("msg","新增员工失败");
        }
        return map;
    }











    //修改操作
    //先查询emp信息，以便回显
    @GetMapping("/updateEmp/{empId}")
    @ResponseBody
    public Emp getEmp(@PathVariable Integer empId){
        Emp emp=empService.getEmp(empId);
        return emp;
    }
    //接着进行更新操作
    @PutMapping("/updateEmp")
    @ResponseBody
    public HashMap<String,Object> updateEmp(@RequestBody Emp emp){
        emp.setUpdateTime(new Date());
        int rows=empService.updateEmp(emp);
        HashMap<String, Object> hashMap = new HashMap<>();
        if(rows>0){
            hashMap.put("status",20000);
            hashMap.put("msg","修改员工成功");
        }else {
            hashMap.put("status",30000);
            hashMap.put("msg","修改员工失败");
        }
        return hashMap;
    }




    //修改员工在职状态(离职、在职、停职)
    @DeleteMapping("/changeEmpState/{empId}/{empState}")
    @ResponseBody
    public HashMap<String,Object> updateEmpState(@PathVariable Integer empId,@PathVariable Integer empState){
        HashMap<String, Object> map = new HashMap<>();
        //设置跟踪字段数据
        //TODO:设置操作员工
        //删除：只是形式的删除，通过修改状态（1）表示删除
        //通过id获取部门
        Emp emp = new Emp(empId, empState.byteValue(), "zhangxu", new Date());
        int i = empService.updateEmp(emp);
        if(i>0){
            map.put("status",20000);
            map.put("msg","修改成功");
        }else{
            map.put("msg","部门操作失败");
        }
        return map;
    }



    //以下为角色分配功能
    @GetMapping("/roleList")
    public List<Role> getRoleById(){
        //不建议在EmpService中定义获取部门集合方法
        return roleService.getList();
    }

    @PutMapping("/roles/updateRoles/{empId}")
    public Map<String,Object> updateRoles(@PathVariable Integer empId,@RequestBody List<Integer> ids){
        Emp emp = new Emp();
        emp.setEmpId(empId);
        //设置追踪数据
        //todo:设置操作员工账户（有权限后设置）
        //设置修改时间
        emp.setUpdateTime(new Date());

        //将List转换为字符串：[1,2,3]  ---> "1,2,3"
        StringBuffer buffer = new StringBuffer();
        for (int i = 0; i < ids.size(); i++) {
            buffer.append(ids.get(i));
            if(i != ids.size() -1){
                buffer.append(",");
            }
        }
        emp.setRoleIds(buffer.toString());

        //调用业务方法新增部门
        int rows = empService.update(emp);

        //准备返回消息对象
        Map<String,Object> map = new HashMap<>();
        if(rows > 0){
            map.put("status",20000);
            map.put("msg","更新角色成功");
        }else{
            map.put("status",30000);
            map.put("msg","更新角色失败");
        }
        return map;
    }



    //员工通讯录下载
    @GetMapping({"/addressBook","/addressBook/{deptIds}"})
    public void talkBookDownLoad(@PathVariable(required = false) String deptIds, HttpServletResponse response){
        List<Dept> deptList=null;
        //判断前端参数是否为空
        if(StringUtils.isEmpty(deptIds)){
            //查询所有部门
            deptList=deptService.getDeptAndEmpList(null);
        }else {
            //将字符串数据"'1','2',..."转换为Set<Integer>,set去重了
            deptList=deptService.getDeptAndEmpList(
                    Arrays.stream(deptIds.split(",")).map(
                            s->Integer.parseInt(s.trim())).collect(Collectors.toSet()));
        }
        Workbook workbook = null;
        try {
            //获取服务器模板文件地址
            String s = ResourceUtils.getURL("classpath:").getPath() + "templates/address_book.xlsx";
            //基于模板文件创建工作簿
            workbook = new XSSFWorkbook(new FileInputStream(s));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        //获取指定索引的表
        Sheet sheetAt = workbook.getSheetAt(0);
        //设置内容开始行号(索引为2)
        int startRow=2;
        //获取模板中内容行的单元格样式（这就是使用模板进行打印输出的意义）
        Row styleRow = sheetAt.getRow(startRow);

        //部门内容列样式
        CellStyle cellStyle = styleRow.getCell(0).getCellStyle();

        //姓名内容列样式
        CellStyle cellStyle1 = styleRow.getCell(1).getCellStyle();

        //性别内容列样式
        CellStyle cellStyle2 = styleRow.getCell(2).getCellStyle();

        //短号内容列样式
        CellStyle cellStyle3 = styleRow.getCell(3).getCellStyle();

        //办公电话内容列样式
        CellStyle cellStyle4 = styleRow.getCell(4).getCellStyle();

        //手机内容列样式
        CellStyle cellStyle5 = styleRow.getCell(5).getCellStyle();

        //邮箱内容列样式
        CellStyle cellStyle6 = styleRow.getCell(6).getCellStyle();

        //遍历部门列表
        for(Dept dept:deptList){
            //获取当前部门的所有员工
            List<Emp> empList = dept.getEmpList();
            //标识需要合并第一行第一列
            int index=0;
            //记录用于合并单元格的开始行号
            int mergedNum = startRow;
            //遍历输出每一行数据
            for(Emp emp:empList){

                //创建新行
                Row row = sheetAt.createRow(startRow);

                //新行第一列
                Cell deptName = row.createCell(0);
                //只有需要合并的所有行中的第一行的第一列需要给单元格设置数据
                if (index == 0) {
                    deptName.setCellValue(dept.getDeptName());
                    index++;
                }
                //将获取的模板样式设置给新列
                deptName.setCellStyle(cellStyle);

                //新行第二列
                Cell empName = row.createCell(1);
                //给新列设置值
                empName.setCellValue(emp.getEmpName());
                //将获取的模板样式设置给新列
                empName.setCellStyle(cellStyle1);

                //新行第三列
                Cell empGender = row.createCell(2);
                empGender.setCellValue(emp.getEmpGender());
                empGender.setCellStyle(cellStyle2);

                //新行第四列
                Cell empCornet = row.createCell(3);
                empCornet.setCellValue(emp.getEmpCornet());
                empCornet.setCellStyle(cellStyle3);

                //新行第五列
                Cell empTel = row.createCell(4);
                empTel.setCellValue(emp.getEmpTel());
                empTel.setCellStyle(cellStyle4);

                //新行第六列
                Cell empMobile = row.createCell(5);
                empMobile.setCellValue(emp.getEmpMobile());
                empMobile.setCellStyle(cellStyle5);

                //新行第七列
                Cell empEmail = row.createCell(6);
                empEmail.setCellValue(emp.getEmpEmail());
                empEmail.setCellStyle(cellStyle6);

                //该换行了
                startRow++;
            }
            //判断合并 行数据，只有超过2行数据才需要合并
            //设置第一列合并单元格，合并单元格(4个参数，分别为起始行，结束行，起始列，结束列)
            // 行和列都是从0开始计数，且起始结束都会合并
            //所有结束行：mergedNum + empList.size()-1



            if(empList.size()>1){
                CellRangeAddress cellRangeAddress =
                        new CellRangeAddress(mergedNum, mergedNum + empList.size() - 1, 0, 0);
                sheetAt.addMergedRegion(cellRangeAddress);
            }
        }

        response.reset();
        response.setContentType("application/ms-excel;charset=UTF-8");
        //下载文件需要设置响应头：注意中文文件名乱码的解决
        try {
            response.setHeader("Content-Disposition", "attachment;filename="
                    + new String(("公司通讯录").getBytes("gbk"), "iso8859-1")+".xlsx");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }


        try {
            //通过将文件数据响应给网页请求实现文件下载（模拟超链接下载文件）
            //将工作簿内容写入响应输出流
            workbook.write(response.getOutputStream());
            response.getOutputStream().flush();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(workbook !=null){
                try {
                    workbook.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            try {
                if(response.getOutputStream() !=null){
                    response.getOutputStream().close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


}
